package com.dhm.web;

import com.alibaba.fastjson.JSON;
import com.dhm.bean.EchartsConfig;
import com.dhm.core.EchartsCore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

@Controller
@RequestMapping("/echarts")
public class ThreadPoolDemo {

    @Autowired
    private SimpMessagingTemplate simpMessagingTemplate;

    private static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10,
                                                                             20,
                                                                             1000L,
                                                                     TimeUnit.MILLISECONDS,
                                                                     new LinkedBlockingQueue<Runnable>(200),
                                                                     new MyThreadFactory());

    @RequestMapping("/showInitThreadPoolInfo")
    @ResponseBody
    public String showInitThreadPoolInfo(@RequestBody EchartsConfig echartsConfig){
        //默认情况下，线程池中并没有任何线程，而是等待有任务到来才创建线程去执行任务
        //默认情况下，在创建了线程池后，线程池中的线程数为0，
        //当有任务来之后，就会创建一个线程去执行任务，
        //当线程池中的线程数目达到corePoolSize后，
        //就会把到达的任务放到缓存队列当中；

        //即在没有任务到来之前就创建一个线程
        //threadPoolExecutor.prestartCoreThread();

        //即在没有任务到来之前就创建corePoolSize个线程
        //threadPoolExecutor.prestartAllCoreThreads();

        List<Map<String,Object>> list = new ArrayList<>();
        Map<String,Object> map = new HashMap<>();
        map.put("y0:taskCount",0);
        map.put("y0:completedTaskCount",0);
        map.put("y0:activeCount",0);
        map.put("y0:poolSize",0);
        //map.put("y0:corePoolSize",0);
        //map.put("y0:maximumPoolSize",0);
        map.put("x:时间", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        list.add(map);
        return EchartsCore.getInstance().adapterLineAndBar(echartsConfig,list).toString();
    }

    @RequestMapping("/threadPoolSize")
    @ResponseBody
    public String threadPoolSize(int corePoolSize,int maximumPoolSize){
        try{
            if(corePoolSize != 0){
                threadPoolExecutor.setCorePoolSize(corePoolSize);
            }
            if(maximumPoolSize != 0){
                threadPoolExecutor.setMaximumPoolSize(maximumPoolSize);
            }
            return "success";
        }catch (Exception e){
            return "fail";
        }
    }

    @RequestMapping("/allowCoreThreadTimeOut")
    @ResponseBody
    public String allowCoreThreadTimeOut(boolean allowCoreThreadTimeOut){
        try{
            //keepAliveTime不能设置为零
            threadPoolExecutor.allowCoreThreadTimeOut(allowCoreThreadTimeOut);
            return "success";
        }catch (Exception e){
            return "fail";
        }
    }

    @RequestMapping("/handlerthreadPool")
    @ResponseBody
    public String handlerThreadPool(int handlerTasksNum){
        try{
            for(int i=0;i<handlerTasksNum;i++){
                threadPoolExecutor.execute(()->{
                    try {
                        Thread.sleep(1000);
                        System.out.println(Thread.currentThread().toString());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                });
            }
            return "success";
        }catch (Exception e){
            return "fail";
        }
    }

    @Scheduled(cron="0/1 * *  * * ? ")
    public void showRealTimeThreadPoolInfo(){
        Map<String,Object> map = new HashMap<>();
        map.put("taskCount",threadPoolExecutor.getTaskCount());
        map.put("completedTaskCount",threadPoolExecutor.getCompletedTaskCount());
        map.put("activeCount",threadPoolExecutor.getActiveCount());
        map.put("poolSize",threadPoolExecutor.getPoolSize());
        map.put("queueSize",threadPoolExecutor.getQueue().size());
//        map.put("corePoolSize",threadPoolExecutor.getCorePoolSize());
//        map.put("maximumPoolSize",threadPoolExecutor.getMaximumPoolSize());
        map.put("xxx",LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        simpMessagingTemplate.convertAndSend("/topic/showRealTimeThreadPoolInfo/data", JSON.toJSONString(map));
    }

    static class MyThreadFactory implements ThreadFactory {
        private final AtomicInteger poolNumber = new AtomicInteger(1);
        private final ThreadGroup group;
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix;

        MyThreadFactory() {
            SecurityManager s = System.getSecurityManager();
            group = (s != null) ? s.getThreadGroup() :
                    Thread.currentThread().getThreadGroup();
            namePrefix = "mypool-" +
                    poolNumber.getAndIncrement() +
                    "-mythread-";
        }

        public Thread newThread(Runnable r) {
            Thread t = new Thread(group, r,
                    namePrefix + threadNumber.getAndIncrement(),
                    0);
            if (t.isDaemon())
                t.setDaemon(false);
            if (t.getPriority() != Thread.NORM_PRIORITY)
                t.setPriority(Thread.NORM_PRIORITY);
            return t;
        }
    }
}
